package com.xiao.hao.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.xiao.hao.constant.CheckParamsEnum;
import com.xiao.hao.exception.BusinessException;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

@Component
@Aspect
@Slf4j
public class CheckParamsAspect {

    @Around("@annotation(checkParamsAnnotation)")
    public Object checkParams(ProceedingJoinPoint point,
                              CheckParamsAnnotation checkParamsAnnotation) throws Throwable {
        log.info("start CheckParamsAspect method  checkParamsAnnotation ={}",
                checkParamsAnnotation.value());
        CheckParamsEnum methodEnum = checkParamsAnnotation.value();

        Object params = point.getArgs()[0];
        Class<?> cls = params.getClass();
        List<Field> fieldList = Lists.newArrayList();
        while (!cls.isAssignableFrom(Object.class)) {
            fieldList.addAll(Arrays.asList(cls.getDeclaredFields()));
            cls = cls.getSuperclass();
        }
        if (ObjectUtil.isEmpty(fieldList)) {
            return point.proceed();
        }

        fieldList.forEach(c -> {
            CheckParamsAnnotation annotation = c.getAnnotation(CheckParamsAnnotation.class);
            try {
                Object value = FieldUtils.readField(c, params, true);
                ApiModelProperty apiModelProperty = c.getAnnotation(ApiModelProperty.class);
                CheckParamsEnum checkParams = ObjectUtil.isEmpty(annotation) ? null :
                        annotation.value();
                if (checkParams != null && CheckParamsEnum.DEFAULT_CHECK != checkParams && (checkParams == methodEnum || CheckParamsEnum.COMMON_CHECK == checkParams)) {
                    if (ObjectUtil.isEmpty(value)) {
                        BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ?
                                "参数不能为空" :
                                apiModelProperty.value() + "不能为空");
                    }
                }

                String regularCheck = ObjectUtil.isEmpty(annotation) ? null :
                        annotation.regularCheck();
                if (StrUtil.isNotEmpty(regularCheck) && ObjectUtil.isNotEmpty(value) && !String.valueOf(value).matches(regularCheck)) {
                    BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ? "格式错误"
                            : apiModelProperty.value() + "格式错误,请重新输入");

                }

                int[] integerListCheck = ObjectUtil.isEmpty(annotation) ? null :
                        annotation.integerListCheck();
                if (integerListCheck != null && integerListCheck.length > 0 && ObjectUtil.isNotEmpty(value) && !ArrayUtils.contains(integerListCheck,
                        (Integer) value)) {
                    BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ? "非法请求," +
                            "请输入规定范围内的值"
                            : apiModelProperty.value() + "非法请求,请输入规定范围内的值");
                }


                String[] stringListCheck = ObjectUtil.isEmpty(annotation) ? null :
                        annotation.stringListCheck();
                if (stringListCheck != null && stringListCheck.length > 0 && ObjectUtil.isNotEmpty(value) && !ArrayUtils.contains(stringListCheck, value)) {
                    BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ? "非法请求," +
                            "请输入规定范围内的值"
                            : apiModelProperty.value() + "非法请求,请输入规定范围内的值");
                }

                int minSize = ObjectUtil.isEmpty(annotation) ? 0 : annotation.min();
                if (minSize != 0 && ObjectUtil.isNotEmpty(value) && String.valueOf(value).length() < minSize) {
                    BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ? "格式错误," +
                            "长度需要大于" + minSize
                            : apiModelProperty.value() + "格式错误,长度需要大于" + minSize);
                }

                int maxSize = ObjectUtil.isEmpty(annotation) ? 0 : annotation.max();
                if (maxSize != 0 && ObjectUtil.isNotEmpty(value) && String.valueOf(value).length() > maxSize) {
                    BusinessException.isTrue(false, ObjectUtil.isEmpty(apiModelProperty) ? "格式错误," +
                            "长度超过限制,最大为" + maxSize
                            : apiModelProperty.value() + "格式错误,长度超过限制,最大为" + maxSize);
                }

            } catch (IllegalAccessException e) {
                BusinessException.isTrue(false, "参数校验异常");
            }
        });
        log.info("end CheckParamsAspect method");
        return point.proceed();

    }
}

